#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

typedef struct queue
{
    int front, rear, size;
    unsigned capacity;
    int *array;
} Queue, *ArrayQueue;

Queue *create(unsigned capacity)
{
    Queue *Q = (Queue *)malloc(sizeof(Queue));
    Q->front = Q->rear = -1;
    Q->capacity = capacity;
    Q->array = (int *)malloc(Q->capacity * sizeof(int));
    return Q;
}

void enQueue(Queue *Q, char value)
{
    if ((Q->front == 0 && Q->rear == Q->capacity - 1) ||
        ((Q->rear + 1) % Q->capacity == Q->front))
    {
        printf("Queue is Full\n");
        return;
    }
    else if (Q->front == -1) /* Insert First Element */
    {
        Q->front = Q->rear = 0;
        Q->array[Q->rear] = value;
    }

    else if (Q->rear == Q->capacity - 1 && Q->front != 0)
    {
        Q->rear = 0;
        Q->array[Q->rear] = value;
    }

    else
    {
        // Q->rear++;
        Q->array[++Q->rear] = value;
    }
    printf("enqueue>>%c\n", value);
}

int deQueue(Queue *Q)
{
    if (Q->front == -1)
    {
        printf("Queue is Empty\n");
        return INT_MIN;
    }

    int data = Q->array[Q->front];
    Q->array[Q->front] = -1;
    if (Q->front == Q->rear)
    {
        Q->front = -1;
        Q->rear = -1;
    }
    else if (Q->front == Q->capacity - 1)
        Q->front = 0;
    else
        Q->front++;

    printf("dequeue>>%c\n", data);
    return data;
}

void displayQueue(Queue *Q)
{
    if (Q->front == -1)
    {
        printf("Queue is Empty\n");
        return;
    }
    printf("Elements in Circular Queue are: \n");
    if (Q->rear >= Q->front)
    {
        for (int i = Q->front; i <= Q->rear; i++)
            printf("%c \n", Q->array[i]);
    }
    else
    {
        for (int i = Q->front; i < Q->capacity; i++)
            printf("%c \n", Q->array[i]);

        for (int i = 0; i <= Q->rear; i++)
            printf("%c \n", Q->array[i]);
    }
}

ArrayQueue createQueue(unsigned capacity)
{
    ArrayQueue q = (ArrayQueue)malloc(sizeof(Queue));
    q->capacity = capacity;
    q->front = q->size = 0;
    q->rear = capacity - 1;
    q->array = (int *)malloc(q->capacity * sizeof(int));
    return q;
}

int main()
{
    // ArrayQueue q = createQueue(5);
    Queue *other = create(10);

    displayQueue(other);

    printf("-----------circular enqueue----------\n");
    char ch;
    while ((ch = getchar()) != '\n')
    {
        enQueue(other, ch);
    }
    
    displayQueue(other);
    printf("current front=%d, rear=%d\n", other->front, other->rear);

    printf("----------circular dequeue-------------\n");

    do
    {
        deQueue(other);
    } while (other->front != -1);

    return 0;
}
